<template>
    <div class="image d-flex flex-column">
        <div class="controller d-flex p-2 align-items-center">
            <template v-if="!choosing">
                
                <!-- 分组、排序 -->
                <div class="input-group w-auto">
                    <div class="input-group-prepend">
                      <span class="input-group-text">分组：</span>
                    </div>
                    <select class="custom-select w-auto" v-model="groupType">
                        <option value="" selected>无</option>
                        <option value="width">宽度</option>
                        <option value="height">高度</option>
                        <option value="aspectRatio">宽高比</option>
                        <option value="size">图片大小</option>
                        <option value="createDate">创建日期</option>
                        <option value="lastModifyDate">最后修改日期</option>
                        <option value="similary">相似度</option>
                    </select>
                    <div class="input-group-addon" style="cursor: pointer; margin-left: -2px" v-if="grouped" v-tooltip title="组别排序" @click="sortGroupDirection *= -1">
                        <span class="input-group-text text-success bg-white">
                            <i class="material-icons align-middle" v-if="sortGroupDirection == 1">arrow_upward</i>
                            <i class="material-icons align-middle" v-else-if="sortGroupDirection == -1">arrow_downward</i>
                        </span>
                    </div>
                </div>

                <template v-if="groupType != 'similary' ">
                    
                    <button class="btn btn-sm btn-link text-success p-1 mr-1" v-if="grouped" v-tooltip title="组内排序"  @click="sortImageDirection = sortImageDirection == 1 ? -1 : sortImageDirection + 1">
                        <i class="material-icons align-middle" v-if="sortImageDirection == 1">arrow_upward</i>
                        <i class="material-icons align-middle" v-else-if="sortImageDirection == -1">arrow_downward</i>
                        <i class="material-icons align-middle" v-else >sort</i>
                    </button>

                    <button class="btn btn-sm btn-link text-success p-1 mr-1" v-else v-tooltip title="按名字排序" @click="sortImageDirection = sortImageDirection == 1 ? -1 : sortImageDirection + 1">
                        <i class="material-icons align-middle" v-if="sortImageDirection == 1">arrow_upward</i>
                        <i class="material-icons align-middle" v-else-if="sortImageDirection == -1">arrow_downward</i>
                        <i class="material-icons align-middle" v-else>sort</i>
                    </button>
                </template>

                <button class="btn btn-sm btn-link text-info p-1 mr-1 ml-auto" @click="$emit('searchByImage')" v-tooltip title='搜索图片'>
                    <i class="material-icons align-middle">image_search</i>
                </button>
                <button class="btn btn-sm btn-link text-info p-1 mr-1" @click="$emit('upload')" v-tooltip title='上传图片'>
                    <i class="material-icons align-middle">cloud_upload</i>
                </button>

                <button class="btn btn-sm btn-link text-muted p-1 mr-1" @click="toggleChooseMode" v-tooltip title='选择图片' v-if="!choosing">
                    <i class="material-icons align-middle" >select_all</i>
                </button>
            </template>
            <template v-else>
                <button class="btn btn-sm btn-link text-danger p-1 mr-1" @click="removeChosed" v-tooltip title='从当前目录移除' v-if="chosedArr.length">
                    <i class="material-icons align-middle">delete</i>
                </button>
                <button class="btn btn-sm btn-link text-success p-1 mr-1" @click="copyChosed" v-tooltip title='复制到...' v-if="chosedArr.length">
                    <i class="material-icons align-middle">move_to_inbox</i>
                </button>
                <button class="btn btn-sm btn-link text-success p-1 mr-1" @click="moveChosed" v-tooltip title='移动到...' v-if="chosedArr.length">
                    <i class="material-icons align-middle">send</i>
                </button>
                <div class="p-1 ml-auto align-middle d-inline-block">
                    已选中: <span class="text-info">{{chosedArr.length}}</span> / <span class="text-secondary">{{images.length}}</span>
                </div>
                
                <button class="btn btn-sm btn-link text-muted p-1 mr-1" @click="toggleChoosedArr" v-tooltip title='反选'>
                    <i class="material-icons align-middle" >compare_arrows</i>
                </button>
                <button class="btn btn-sm btn-link text-muted p-1 mr-1" @click="toggleChooseMode" v-tooltip title='取消'>
                    <i class="material-icons align-middle" >close</i>
                </button>
            </template>
            
        </div>
        <div class="list-container">
            <div>
                <div :class="[grouped ? 'card m-2' : '']" v-for="obj of groupedInfo" v-if="imagesOf(obj).length">
                    <div class="card-header" v-if="grouped">
                        {{obj._id}}
                    </div>
                    <div :class="[grouped ? 'card-body' : '']">
                        <div :class="[
                            'item img-thumbnail position-relative',
                            choosing ? 
                                {
                                    chosed: !!chosedMap[image._id],
                                    unchosed: !chosedMap[image._id]
                                }
                            : 
                                {}
                            ]" v-for="image in imagesOf(obj)">
                            <button class="btn btn-sm btn-link text-info m-2 p-0" style="position: absolute; top: 0; right: 0; z-index: 1;" >
                                <i class="material-icons align-middle" v-if="choosing" @click="enterViewer(image)">image</i>
                            </button>
                            <lazyImg
                                :image="{
                                    src: image.baseInfo.src + '?thumb=true',
                                    alt: image.baseInfo.name
                                }"
                                :size="150"
                                :key="image._id"
                                @smart-click="itemClick(image)"
                            ></lazyImg>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <!-- imageCard -->
        <div class="viewer-area" v-if="viewing">
            <imageCard
                :doc="viewing"
                :key="viewing._id"
                @close="exitViewer"
                @rename="doc => $emit('rename', doc)"
                @addExtendInfo="doc => $emit('addExtendInfo', doc)"
                @editExtendInfo="(doc, info) => $emit('editExtendInfo', doc, info)"
                @removeExtendInfo="(doc, info) => $emit('removeExtendInfo', doc, info)"
            >
                <div class="align-middle d-inline-block p-1" slot="footer-bar">

                    
                    <span class="text-info align-middle mx-1" v-if="viewingGroupInfo">
                        {{viewingGroupInfo.target._id }}
                    </span>
            
                    <template v-if="choosing">
                        <label class="custom-control custom-checkbox d-inline-block mr-1" >
                          <input type="checkbox" class="custom-control-input" :checked="!!chosedMap[viewing._id]" @change="toggleChosedItem(viewing)">
                          <div class="custom-control-label">{{!!chosedMap[viewing._id] ? '已选中' : '未选中'}}</div>
                        </label>
                    </template>

                    <button class="prev btn btn-outline-info mx-1 p-1 rounded-circle"
                        :disabled="viewingIndex == 0"
                        @click="viewingIndex = viewingIndex - 1"
                    >
                        <i class="material-icons align-middle">navigate_before</i>
                    </button>

                    <button class="next btn btn-outline-info mx-1 p-1 rounded-circle"
                        :disabled="viewingIndex + 1 >= images.length"
                        @click="viewingIndex = viewingIndex + 1"
                    >
                        <i class="material-icons align-middle">navigate_next</i>
                    </button>
                </div>
             </imageCard>
        </div>
        <!-- loading svg -->
        <loading :active.sync="isLoading"
        :can-cancel="false"
        backgroundColor='transparent'
        loader='dots'
        :is-full-page="false"></loading>
    </div>
</template>
<script type="text/javascript">
// 1. 选择功能
/*
    1. 移动时间 2. 复制事件 3. 移除事件
        多选功能
    4. 重命名事件
    5. 上传事件
    6. 添加扩展信息
    7. 移除扩展信息
    8. 修改扩展信息
*/
import _ from 'lodash'
import Scrollbar from 'smooth-scrollbar'

import $ from 'jquery'

import jqAjax from '../plugin/jqAjax'
import {constant as ajaxConstant} from '../plugin/jqAjax'

import lazyImg from './lazy-img'
import imageCard from './image-card'
import {constant as imageCardConstant} from './image-card'
import imageViewer from './image-viewer'
import {constant as imageViewerConstant, scaleController, dragController, resizeController} from './image-viewer'

import Loading from 'vue-loading-overlay';
import 'vue-loading-overlay/dist/vue-loading.css';

var constant = Object.assign({
    CARD: 'card',
    VIEWER: 'viewer',

}, ajaxConstant, imageCardConstant, imageViewerConstant);

export default {
    name: 'image-list',
    components: {Loading, lazyImg, imageCard, imageViewer},
    mixins: [jqAjax],
    props: {
        content: {
            type: Array,
            required: true
        },
        dir_id: {
            type: String,
            required: true
        }
    },
    data() {
        return {
            images: [],

            choosing: false,
            chosedArr: [],

            viewing: null,

            mGroupType: '',
            groupedInfo: [null],
            sortGroupDirection: 1,

            sortImageDirection: 0,
        }
    },
    computed: {
        grouped() {
            return !!this.groupedInfo[0];
        },
        chosedIds() {
            return this.chosedArr.map(x => x._id);
        },
        chosedMap() {
            return this.chosedArr.reduce((a, b) => {
                a[b._id] = b;
                return a;
            }, {});
        },
        imageMap() {
            return this.images.reduce((a, b) => {
                a[b._id] = b;
                return a;
            }, {});
        },
        groupType: {
            get() {
                return this.mGroupType;
            },
            set(nv) {
                var vm = this;
                if (nv == this.mGroupType) {
                    return;
                }
                vm.groupFor(nv);
            }
        },
        viewingGroupInfo() {
            var vm = this;
            if (vm.grouped && vm.viewing) {
                var rs = vm.whichGroup(vm.viewing);
                return rs[0] != -1 ? { target: vm.groupedInfo[rs[0]], index: rs[1] } : null;
            } else {
                return null;
            }
        },
        viewingIndex: {
            get() {
                var vm = this;
                if (!vm.grouped) {
                    return vm.images.indexOf(this.viewing);
                } else {
                    var rs = vm.whichGroup(vm.viewing);
                    if (rs[0] == -1) {
                        return -1;
                    } else {
                        var index = 0;
                        $.each(vm.groupedInfo, (i, o) => {
                            if (i >= rs[0]) {
                                return false;
                            }
                            index += o.arr.length;
                        });
                        index += rs[1];
                        return index;
                    }
                }
            },
            set(nv) {
                var vm = this;
                if (!vm.grouped) {
                    if (nv < 0 || nv >= this.images.length) {
                        return;
                    } else {
                        vm.viewing = vm.images[nv];
                    }
                } else {
                    var prevSum = 0, target = null;
                    $.each(vm.groupedInfo, (i, o) => {
                        if (o.arr.length >= (nv + 1) - prevSum) {
                            target = o.arr[nv-prevSum];
                            return false;
                        }
                        prevSum += o.arr.length;
                    });
                    if (!target) {
                        return;
                    }
                    vm.viewing = vm.imageMap[target];
                }
            }
        }
    },
    methods: {
        imagesOf(obj) {
            var vm = this;
            if (!obj) {
                return vm.images;
            } else {
                return obj.arr.map(x => vm.imageMap[x]).filter(x => x);
            }
        },
        itemClick(image) {
            var vm = this;
            if (vm.choosing) {
                vm.toggleChosedItem(image);
            } else {
                vm.enterViewer(image);
            }
        },
        toggleChosedItem(image) {
            var vm = this;
            vm.chosedArr = _.xor(vm.chosedArr, [image]);
        },
        toggleChooseMode() {
            var vm = this;
            if (vm.choosing) {
                vm.choosing = false;
                vm.chosedArr = [];
            } else {
                vm.choosing = true;
            }
        },
        toggleChoosedArr() {
            var vm = this;
            vm.chosedArr = _.without(vm.images, ...vm.chosedArr);
        },
        removeChosed() {
            this.$emit('remove', this.chosedIds);
        },
        moveChosed() {
            this.$emit('move', this.chosedIds);
        },
        copyChosed() {
            this.$emit('copy', this.chosedIds);
        },
        async loadData() {
            var vm = this;
            var res = await vm.ajaxPost('/model/image/list', {
                _id: vm.dir_id
            });
            vm.images = res.images.filter(x => vm.content.indexOf(x._id) !== -1);
        },
        enterViewer(image) {
            var vm = this;
            vm.viewing = image;
        },
        exitViewer() {
            var vm = this;
            vm.viewing = null;
        },
        whichGroup(doc) {
            var vm = this;
            var rs = [-1, -1];
            if (!vm.grouped) {
                return rs;
            } else {
                $.each(vm.groupedInfo, (index, obj) => {
                    var i = obj.arr.indexOf(doc._id);
                    if (i != -1) {
                        rs[0] = index;
                        rs[1] = i;
                        return false;
                    }
                });
                return rs;
            }
        },
        async groupFor(nv) {
            var simpleGroupBy = function(lb, bt, sfn, ks=(a,b)=> {return a - b;}) {
                var t = _.groupBy(vm.images, function(obj) {
                    return lb(obj);
                });
                var keys = Object.keys(t).sort((a, b) => ks(a, b) * vm.sortGroupDirection);
                return keys.map(x => {
                    return {_id: bt(x), arr: t[x].sort(
                        (a, b) => sfn(a, b) * vm.sortImageDirection
                    ).map(img => img._id)};
                });
            }, handler = {
                '': function() {
                    return [null];
                },
                width() {
                    return simpleGroupBy(x => parseInt(x.baseInfo.width / 100), x => `${x}00 ~ ${x}99`, (a, b) => a.baseInfo.width - b.baseInfo.width);
                },
                height() {
                    return simpleGroupBy(x => parseInt(x.baseInfo.height / 100), x => `${x}00 ~ ${x}99`, (a, b) => a.baseInfo.height - b.baseInfo.height);
                },
                aspectRatio() {
                    return simpleGroupBy(x => parseInt(x.baseInfo.aspectRatio), x => `${x} ~ ${x}.99`, (a, b) => a.baseInfo.aspectRatio - b.baseInfo.aspectRatio)
                },
                size() {
                    return simpleGroupBy(x => parseInt(x.baseInfo.size / (1024 * 1024)), x => `${x}mb ~ ${x}.99mb`, (a, b) => a.baseInfo.size - b.baseInfo.size);
                },
                createDate() {
                    return simpleGroupBy(x => new Date(x.baseInfo.createDate).toLocaleDateString(),
                        x => `${x}`, (a, b) => a.baseInfo.createDate - b.baseInfo.createDate,
                        (a, b) => Date.parse(a) - Date.parse(b)
                    );
                },
                lastModifyDate() {
                    return simpleGroupBy(x => new Date(x.baseInfo.lastModifyDate).toLocaleDateString(),
                        x => `${x}`, (a, b) => a.baseInfo.lastModifyDate - b.baseInfo.lastModifyDate,
                        (a, b) => Date.parse(a) - Date.parse(b)
                    );
                },
                async similary() {
                    var res = await vm.ajaxPost(`/model/image/group/similary`, {
                        _id: vm.dir_id
                    });
                    if (vm.sortGroupDirection == -1) {
                        res.result.reverse();
                    }
                    return res.result;
                }
            }, vm = this;
            if (! handler.hasOwnProperty(nv)) {
                return;
            } else {
                if (nv !== 'similary') {
                    vm.reposition();
                }
                vm.mGroupType = nv;
                vm.groupedInfo = await handler[nv]();
            }
        },
        reposition() {
            var vm = this;
            var indexMap = vm.content.reduce((a, b, i) => {
                a[b] = i;
                return a;
            }, {});
            vm.images = vm.images.slice().sort((a, b) => indexMap[a._id] - indexMap[b._id]);
        },
        sortForName() {
            var vm = this;
            var sortByName = function(a, b) {
                var a_l = a.length, b_l = b.length, c_a, c_b, n_a, n_b, s_a, e_a, s_b, e_b;
                for (var i = 0, j = 0; i < a_l && j < b_l; i++, j++) {
                    c_a = a.charCodeAt(i);
                    c_b = b.charCodeAt(j);
                    if (48 <= c_a && c_a <= 57 && 48 <= c_b && c_b <= 57) {
                        // compare number
                        e_a = s_a = i;
                        e_b = s_b = j;
                        while (48 <= c_a && c_a <= 57 && e_a < a_l) {
                            c_a = a.charCodeAt(++e_a);
                        }
                        while (48 <= c_b && c_b <= 57 && e_b < b_l) {
                            c_b = b.charCodeAt(++e_b);
                        }
                        n_a = parseInt(a.substring(s_a, e_a));
                        n_b = parseInt(b.substring(s_b, e_b));
                        if (n_a == n_b) {
                            i = e_a - 1;
                            j = e_b - 1;
                            continue;
                        } else {
                            return n_a - n_b;
                        }
                    } else if (c_a == c_b) {
                        continue;
                    } else {
                        return c_a - c_b;
                    }
                }
                return 0;
            };
            if (vm.sortImageDirection == 0) {
               vm.reposition();
            } else {
                vm.images.sort((a, b) => {
                    return sortByName(a.baseInfo.name, b.baseInfo.name) * vm.sortImageDirection;
                });
            }
        },
        fresh() {
            var vm = this;
            vm.choosing = false;
            vm.chosedArr = [];
            vm.groupFor(vm.groupType);
            if (!vm.grouped) {
                vm.sortForName();
            }
        },

    },
    watch: {
        sortGroupDirection(nv) {
            var vm = this;
            if (!vm.grouped) {
                return;
            }
            vm.groupedInfo.reverse();
        },
        sortImageDirection(nv, ov) {
            var vm = this;
            if (vm.grouped) {
                if (!nv) {
                    vm.reposition();
                }
                vm.groupFor(vm.groupType);
            } else {
                vm.sortForName();
            }
        },
        async content() {
            var vm = this;
            await vm.loadData();
            vm.fresh();
        },
        images: {
            deep: true,
            handler(nv, ov) {
                var vm = this;
                if (vm.grouped && nv === ov) {
                    vm.groupFor(vm.groupType);
                }
            }
        },
        grouped(nv, ov) {
            var vm = this;
            if (!nv) {
                vm.sortForName();
            }
        }
    },
    created() {
        
    },
    async mounted() {
        var vm = this;
        vm.listContainer = vm.$el.querySelector('.list-container');
        vm.scrollbar = Scrollbar.init(vm.listContainer);

        vm.loadData();

    },
    destroyed() {
        var vm = this;
        Scrollbar.destroy(vm.listContainer);
    }
}
</script>
<style type="text/css" scoped>
.image {
    height: 100%;
}

.item {
    display: inline-block;
    width: 150px;
    height: 150px;
    margin: 8px;
    /* line-height: 150px;
    text-align: center; */
    box-sizing: content-box;
    vertical-align: top;
}

.item.chosed {
    opacity: 1;
    border-color: orange;
}

.item.unchosed {
    opacity: 0.5;
}

.viewer-area {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}

</style>